package com.tang.juc.aqs;

import lombok.Getter;
import lombok.Setter;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;


/**
 * @author tlm
 * @version 1.0
 * @date 2020/4/22 18:09
 * 自定义锁，效仿ReentrantLock实现
 */
public class CustomLock {

    /*
     * 当前加锁的状态，记录加锁的次数
     */
    @Getter
    @Setter
    private volatile int state = 0;

    /*
    当前持有锁的线程
     */
    @Getter
    @Setter
    private Thread lockHolder;

    private ConcurrentLinkedQueue<Thread> waiters = new ConcurrentLinkedQueue<>();

    /**
     * 尝试获取锁
     *
     * @return
     */
    public boolean acquire() {
        //获取进来的线程
        Thread current = Thread.currentThread();
        //初始状态
        int c = getState();
        if (c == 0) {//如果c==0,证明同步器还没被持有
            if ((waiters.size() == 0 || current==waiters.peek()) && compareAndSwapState(0, 1)) {
                setLockHolder(current);
                return true;
            }

        }
        return false;
    }

    /**
     * 加锁
     */
    public void lock() {
        //加锁成功
        if (acquire()) {
            return;
        }
        Thread current = Thread.currentThread();
        //把所有获取失败的线程放入阻塞队列中等待
        waiters.add(current);
        for (; ; ) {
            if ((current==waiters.peek()) && acquire()) {
                //线程拿到锁后从阻塞队列中移除
                waiters.poll();
                return;
            }
            //如果仍然没有获取到锁，阻塞当前线程
            LockSupport.park();
        }
    }

    /**
     * 解锁
     */
    public void unlock() {
        if (Thread.currentThread() != lockHolder) {
            throw new RuntimeException("lockHolder is not current thread");
        }
        int state = getState();
        if (compareAndSwapState(state, 0)) {
            setLockHolder(null);
            //拿到阻塞队列中的第一个线程
            Thread first = waiters.peek();
            if (first != null) {
                //释放线程
                LockSupport.unpark(first);
            }
        }
    }

    /**
     * CAS原子操作
     */
    public final boolean compareAndSwapState(int except, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, except, update);
    }

    private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();

    /*
    state在内存中的偏移量
     */
    private static final long stateOffset;

    static {
        try {
            stateOffset = unsafe.objectFieldOffset(CustomLock.class.getDeclaredField("state"));
        } catch (Exception e) {
            throw new Error();
        }
    }

}


class UnsafeInstance {
    /**
     * 利用反射机制获取获取Unsafe对象
     *
     * @return
     */
    public static Unsafe reflectGetUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
